<?php

/**
 * 设置数据缓存方法
 * $key 缓存键名，如：test_0001
 * $data 要缓存的数据，如：array('a','b'),可以是变量、字符、数组及所有数据类型
 * $timeout 缓存的生命周期 秒，如：660  false 为不过期
 * * 使用方法：在模板<?php echo SetCxuuCache('test_0001',array('a','b'),600);?> 
 */

function SetCxuuCache($key, $data, $timeout = false)
{
    switch ($GLOBALS['ZPHP_CONFIG']['DB']['cache_mod']) {
        case 1:
            return libs\cache::R($key, $data, $timeout, 1);
        case 2:
            return libs\cache::M($key, $data, $timeout, 1);
        default:
            return libs\cache::F($key, $data, $timeout, 1);
    }
}

/**
 * 获取数据缓存方法
 * $key 缓存对应的键名，如：test_0001
 *  * 使用方法：在模板<?php echo GetCxuuCache('test_0001');?> 
 * @return [type] 数据类型和缓存的数据对应 
 */
function GetCxuuCache($key)
{
    switch ($GLOBALS['ZPHP_CONFIG']['DB']['cache_mod']) {
        case 1:
            return libs\cache::R($key);
        case 2:
            return libs\cache::M($key);
        default:
            return libs\cache::F($key);
    }
}


/* 
 *  缓存清除方法  
 */
function DelCxuuCache($key)
{
    switch ($GLOBALS['ZPHP_CONFIG']['DB']['cache_mod']) {
        case 1:
            $c = libs\cache::Redis();
            return $c->del('z-php-lock:' . $key);
        case 2:
            $c = libs\cache::Memcached();
            return $c->delete('z-php-lock:' . $key);
        default:
            IsFullPath($key) || $key = P_CACHE . $key;
            return unlink($key);
    }
}

//过滤变量   HTML 转义字符 '"<>& 以及 ASCII 值小于 32 的字符。
function VarFilter($var)
{
    return trim(filter_var($var, FILTER_SANITIZE_SPECIAL_CHARS)) ?: null;
}


/**
 * 输出json格式数据（脚本中断）
 * @param  [type] $data [description]
 * @return [type]       [description]
 */
function Response($data = null)
{
    header('Content-Type:application/json; charset=utf-8');
    die(json_encode($data, JSON_UNESCAPED_UNICODE));
}

/**
 * 数组转json
 */
function JsonEncode($arr)
{
    return json_encode($arr, 320); //JSON_FORCE_OBJECT
}

/**
 * json转数组
 */
function JsonDecode($object)
{
    return json_decode($object, true);
}


/**
 * 页面跳转
 * @param  [type] $url [description]
 * @return [type]      [description]
 */
function Redirect($url = null)
{
    header("Content-type: text/html; charset=utf-8");
    die(header("Location:" . $url));
}


/**
 * 获取客户端ip地址
 * @return string
 */
function GetIp()
{
    $ip = false;
    empty($_SERVER['HTTP_CLIENT_IP']) || $ip = $_SERVER['HTTP_CLIENT_IP'];
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $ips = explode(', ', $_SERVER['HTTP_X_FORWARDED_FOR']);
        if ($ip) {
            array_unshift($ips, $ip);
            $ip = false;
        }
        $count = count($ips);
        for ($i = 0; $i != $count; $i++) {
            if (!preg_match('/^(10│172.16│192.168)./', $ips[$i])) {
                $ip = $ips[$i];
                break;
            }
        }
    }
    return $ip ?: $_SERVER['REMOTE_ADDR'];
}

/**
 * 格式化显示时间
 * $t DateTime
 * $f Y/m/d H:i:s
 * 使用方法：在模板<?php echo FTime('2020-05-05','Y-m-d');?> 
 * */
function FTime($t, $f)
{
    return date_format(date_create($t), $f);
}

/**
 * 时间转化为多久前
 * @param  $date datetime 时间
 * @return date('Y-m-d H:i:s',time());
 */

// function HTime($date)
// {
//     $time = strtotime($date);
//     $time = time() - $time;
//     if (is_numeric($time)) {
//         $value = array(
//             "years" => 0, "days" => 0, "hours" => 0,
//             "minutes" => 0, "seconds" => 0,
//         );
//         if ($time >= 31556926) {
//             $value["years"] = floor($time / 31556926);
//             $time = ($time % 31556926);
//             $t = $value["years"] . '年前';
//         } elseif (31556926 > $time && $time >= 86400) {
//             $value["days"] = floor($time / 86400);
//             $time = ($time % 86400);
//             $t = $value["days"] . '天前';
//         } elseif (86400 > $time && $time >= 3600) {
//             $value["hours"] = floor($time / 3600);
//             $time = ($time % 3600);
//             $t = $value["hours"] . '小时前';
//         } elseif (3600 > $time && $time >= 60) {
//             $value["minutes"] = floor($time / 60);
//             $time = ($time % 60);
//             $t = $value["minutes"] . '分钟前';
//         } else {
//             $t = $time . '秒前';
//         }
//         return $t;
//     } else {
//         return date('Y-m-d H:i:s', time());
//     }
// }

function HTime($date)
{
    $ts = strtotime($date);
    // 如果无法解析时间，返回当前时间字符串（与原实现保持一致）
    if ($ts === false) {
        return date('Y-m-d H:i:s', time());
    }

    $diff = time() - $ts;
    // 未来时间或极小差值统一为刚刚，避免负数秒显示
    if ($diff <= 0) {
        return '刚刚';
    }

    // 单位映射（从大到小），循环判断以减少重复代码
    $units = [
        31556926 => '年前',
        86400 => '天前',
        3600 => '小时前',
        60 => '分钟前',
    ];

    foreach ($units as $seconds => $label) {
        if ($diff >= $seconds) {
            $count = (int) floor($diff / $seconds);
            return $count . $label;
        }
    }

    // 少于 60 秒
    return $diff . '秒前';
}



/*
 * 根据二维数组某个字段的值查找数组
 * @param array $data 待过滤数组
 * @param string $field 要查找的字段
 * @param $value 要查找的字段值
 * @return array 返回所有符合要求的数组集合
	$data = array( 
		0=>array( 
		        'id'=>1, 
		        'name'=>'a' 
		), 
		.... 
		3=>array( 
		        'id'=>4, 
		        'name'=>'d' 
		), 
	); 
	$res = FilterArrayByValue($data,'name','d'); 
	$result['name'] = array_column($res,'name');
	$result['theme'] = array_column($res,'theme');
	最终输出：
	array(2) {
	  ["name"] =>array(1) {
		[0] =>string(12) "电子产品"
	  }
	  ["theme"] =>array(1) {
		[0] =>string(0) ""
	  }
	} */

function FilterArrayByValue(array $data, string $field, $value)
{
    return array_filter($data, function ($row) use ($field, $value) {
        if (isset($row[$field])) {
            return $row[$field] == $value;
        }
    });
}

//根据已经查询到的数组，查找指定的一条数据
// $array  为要查找后输出的数组键
// $array = ['name', 'theme', 'contheme', 'id', 'pid', 'num', 'urlname'];
function FindOneArrayBYFilter(array $data, string $field, $value, array $array)
{
    $find = FilterArrayByValue($data, $field, $value);
    $findRes = [];
    foreach ($array as $key => $vo) {
        $findRes[$key] = array_column($find, $vo);
    }
    $res = [];
    foreach ($findRes as $key => $vo) {
        $res[$array[$key]] = $vo[0];
    }
    return $res;
}


/**
 * 加密函数
 * @param string $txt 需要加密的字符串
 * @param string $key 密钥
 * @return string 返回加密结果
 */
function Encrypt($txt, $key = 'cxuu_dzh')
{
    if (empty($txt))
        return $txt;
    if (empty($key))
        $key = md5($key);
    $chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.";
    $ikey = "-x6g6ZWm2G9g_vr0Bo.pOq3kRIxsZ6rm";
    $nh1 = rand(0, 64);
    $nh2 = rand(0, 64);
    $nh3 = rand(0, 64);
    $ch1 = $chars[$nh1];
    $ch2 = $chars[$nh2];
    $ch3 = $chars[$nh3];
    $nhnum = $nh1 + $nh2 + $nh3;
    $knum = 0;
    $i = 0;
    while (isset($key[$i]))
        $knum += ord($key[$i++]);
    $mdKey = substr(md5(md5(md5($key . $ch1) . $ch2 . $ikey) . $ch3), $nhnum % 8, $knum % 8 + 16);
    $txt = base64_encode(time() . '_' . $txt);
    $txt = str_replace(array('+', '/', '='), array('-', '_', '.'), $txt);
    $tmp = '';
    $j = 0;
    $k = 0;
    $tlen = strlen($txt);
    $klen = strlen($mdKey);
    for ($i = 0; $i < $tlen; $i++) {
        $k = $k == $klen ? 0 : $k;
        $j = ($nhnum + strpos($chars, $txt[$i]) + ord($mdKey[$k++])) % 64;
        $tmp .= $chars[$j];
    }
    $tmplen = strlen($tmp);
    $tmp = substr_replace($tmp, $ch3, $nh2 % ++$tmplen, 0);
    $tmp = substr_replace($tmp, $ch2, $nh1 % ++$tmplen, 0);
    $tmp = substr_replace($tmp, $ch1, $knum % ++$tmplen, 0);
    return $tmp;
}

/**
 * 解密函数
 * @param string $txt 需要解密的字符串
 * @param string $key 密匙
 * @return string 字符串类型的返回结果
 */
function Decrypt($txt, $key = 'cxuu_dzh', $ttl = 0)
{
    if (empty($txt))
        return $txt;
    if (empty($key))
        $key = md5($key);
    $chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.";
    $ikey = "-x6g6ZWm2G9g_vr0Bo.pOq3kRIxsZ6rm";
    $knum = 0;
    $i = 0;
    $tlen = @strlen($txt);
    while (isset($key[$i]))
        $knum += ord($key[$i++]);
    $ch1 = @$txt[$knum % $tlen];
    $nh1 = strpos($chars, $ch1);
    $txt = @substr_replace($txt, '', $knum % $tlen--, 1);
    $ch2 = @$txt[$nh1 % $tlen];
    $nh2 = @strpos($chars, $ch2);
    $txt = @substr_replace($txt, '', $nh1 % $tlen--, 1);
    $ch3 = @$txt[$nh2 % $tlen];
    $nh3 = @strpos($chars, $ch3);
    $txt = @substr_replace($txt, '', $nh2 % $tlen--, 1);
    $nhnum = $nh1 + $nh2 + $nh3;
    $mdKey = substr(md5(md5(md5($key . $ch1) . $ch2 . $ikey) . $ch3), $nhnum % 8, $knum % 8 + 16);
    $tmp = '';
    $j = 0;
    $k = 0;
    $tlen = @strlen($txt);
    $klen = @strlen($mdKey);
    for ($i = 0; $i < $tlen; $i++) {
        $k = $k == $klen ? 0 : $k;
        $j = strpos($chars, $txt[$i]) - $nhnum - ord($mdKey[$k++]);
        while ($j < 0)
            $j += 64;
        $tmp .= $chars[$j];
    }
    $tmp = str_replace(array('-', '_', '.'), array('+', '/', '='), $tmp);
    $tmp = trim(base64_decode($tmp));
    if (preg_match("/\d{10}_/s", substr($tmp, 0, 11))) {
        if ($ttl > 0 && (time() - substr($tmp, 0, 11) > $ttl)) {
            $tmp = null;
        } else {
            $tmp = substr($tmp, 11);
        }
    }
    return $tmp;
}